// 最长递增子序列字典序最小的结果
// 给定数组arr，设长度为n
// 输出arr的最长递增子序列
// 如果有多个答案，请输出其中字典序最小的
// 注意这道题的字典序设定（根据提交的结果推论的）：
// 每个数字看作是单独的字符，比如120认为比36的字典序大
// 保证从左到右每个数字尽量小
// 测试链接 : https://www.nowcoder.com/practice/30fb9b3cab9742ecae9acda1c75bf927
// 测试链接 : https://www.luogu.com.cn/problem/T386911
// 提交以下的code，可以直接通过

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 100001;
int nums[MAXN];
int f[MAXN];
int ends[MAXN];
int ans[MAXN];
int n, k;

// ends[有效区]从大到小的
// ends : 10 9 6 4 3 1
// 二分的方式找<=num的最左位置
int bs(int len, int num)
{
    int l = 0, r = len - 1, m, ans = -1;
    while(l <= r)
    {
        m = (l + r) >> 1;
        if(::ends[m] <= num)
        {
            ans = m;
            r = m - 1;
        }
        else l = m + 1;
    }
    return ans;
}

// f[i] : 必须以i位置的数字开头的情况下，最长递增子序列长度
// 填好f表 + 返回最长递增子序列长度
int dp()
{
    int len = 0;
    for(int i = n - 1, find; i >= 0; --i)
    {
        find = bs(len, nums[i]);
        if(find == -1)
        { 
            ::ends[len++] = nums[i];
            f[i] = len;
        }
        else
        {
            ::ends[find] = nums[i];
            f[i] = find + 1;
        }
    }
    return len;
}

// 讲解072 - 最长递增子序列及其扩展
void lis()
{
    k = dp();
    fill(ans, ans + k, INT_MAX);
    for(int i = 0; i < n; ++i)
    {
        if(f[i] == k)
        {
            // 注意这里
            // 为什么不用判断直接设置
            // 有讲究，课上重点讲了
            // nums: 4 ... m
            // dp :  6 ... 6
            // 则 m <= 4，此时以 nums[i] 开头的子序列字典序更小
            ans[0] = nums[i];
        }
        else
        {
            if(ans[k - f[i] - 1] < nums[i])
            {
                // 分析同上
                // 注意这里
                // 为什么只需要判断比前一位(ans[k-dp[i]-1])大即可
                // 有讲究，课上重点讲了
                ans[k - f[i]] = nums[i];
            }
        }
    }
}


int main()
{
    scanf("%d", &n);
    for(int i = 0; i < n; ++i) scanf("%d", &nums[i]);
    lis();
    for(int i = 0; i < k; ++i)
    {
        printf("%d ", ans[i]);
    }
    printf("\n");

    return 0;
}